package com.finance.cooperate.feature.builder.submodel;

import com.finance.cooperate.common.constant.Constant;
import com.finance.cooperate.common.utils.ClassificationModel;
import com.finance.cooperate.common.utils.StringUtil;
import com.finance.cooperate.dao.local.cache.PmmlPool;
import com.finance.cooperate.feature.base.ReaderImpl;
import com.finance.cooperate.feature.core.feature.FeatureDefinition;
import org.dmg.pmml.FieldName;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName ModelResult
 * @Description PMML模型结果输出
 * @Author shen
 * @Date 2022/5/26 11:37
 * @Modify ...
 */
public class PmmlModelResult extends ReaderImpl {


    @Override
    public Map<String, String> read(String userId) {


        Double device230815 = this.exeModel("model/sub/pmml/model_sub_device_230815.pmml");
        super.put(FeatureDefinition.f_model_sub_device_230815, device230815);

        Double install230814 = this.exeModel("model/sub/pmml/model_sub_install_230814.pmml");
        super.put(FeatureDefinition.f_model_sub_install_230814, install230814);

        Double time230814 = this.exeModel("model/sub/pmml/model_sub_time_230814.pmml");
        super.put(FeatureDefinition.f_model_sub_time_230814, time230814);

        Double scrapy230816 = this.exeModel("model/sub/pmml/model_sub_scrapy_230816.pmml");
        super.put(FeatureDefinition.f_model_sub_scrapy_230816, scrapy230816);

        Double sms230812 = this.exeModelHandMissing("model/sub/pmml/model_sub_sms_words_230812.pmml", FeatureDefinition.f_have_sms);
        super.put(FeatureDefinition.f_model_sub_sms_words_230812, sms230812);

        Double smsOppo230812 = this.exeModelHandMissing("model/sub/pmml/model_sub_sms_oppo_230913.pmml", FeatureDefinition.f_have_sms);
        super.put(FeatureDefinition.f_model_sub_sms_oppo_230913, smsOppo230812);



/*
        Double device231005 = this.exeModel("model/sub/pmml/model_sub_device_231005.pmml");
        super.put(FeatureDefinition.f_model_sub_device_231005, device231005);

        Double install231005 = this.exeModel("model/sub/pmml/model_sub_install_231005.pmml");
        super.put(FeatureDefinition.f_model_sub_install_231005, install231005);

        Double scrapy231005 = this.exeModel("model/sub/pmml/model_sub_scrapy_231005.pmml");
        super.put(FeatureDefinition.f_model_sub_scrapy_231005, scrapy231005);

        Double time231005 = this.exeModel("model/sub/pmml/model_sub_time_231005.pmml");
        super.put(FeatureDefinition.f_model_sub_time_231005, time231005);

        Double sms231006 = this.exeModelHandMissing("model/sub/pmml/model_sub_sms_231006.pmml", FeatureDefinition.f_have_sms);
        super.put(FeatureDefinition.f_model_sub_sms_231006, sms231006);
*/






        // 大模型，放后面，可能用前面的

        Double modelV1 = this.exeModel("model/V1_230817.pmml");
        super.put(FeatureDefinition.f_model_v1_230817, modelV1);

        Double modelV2 = this.exeModel("model/V2_230914.pmml");
        super.put(FeatureDefinition.f_model_v2_230914, modelV2);



        Double modelV3 = this.exeModel("model/V3_230928.pmml");
        super.put(FeatureDefinition.f_model_v3_230928, modelV3);

        Double modelV4 = this.exeModel("model/V4_231007.pmml");
        super.put(FeatureDefinition.f_model_v4_231007, modelV4);




        return super.getResult();
    }



    /**
     * @Author shen
     * @Description 根据传入变量判断是否为缺失值【为1表示有值】
     * @Date 15:27 2022/11/16
     * @Param [path]
     * @return java.lang.Double
     **/
    private Double exeModelHandMissing(String path, FeatureDefinition flagKey) {

        // 如果判断不为缺失值，才继续计算
        String flagMiss = super.get(flagKey);
        if (!StringUtil.isEmptyOrNvl(flagMiss)) {

            if (Integer.valueOf(flagMiss).equals(1)) {

                ClassificationModel model = PmmlPool.getInstance().getModel(path);

                List<String> featureNames = model.getFeatureNames();
                Map<FieldName, Number> waitPreSample = new HashMap<>();

                for (String name : featureNames) {

                    // 获取特征值：
                    Double value = -999.0;

                    String v = super.get(name);
                    if (StringUtil.isEmptyOrNvl(v)) {
                        boolean oneHot = FeatureDefinition.isOneHot(name);
                        if (oneHot) {
                            value = Double.valueOf(Constant.IS_NO_HIT);
                        } else {
                            value = Double.valueOf(Constant.MISSING_VALUE);
                        }
                        // 设置完成放到map中
                        super.put(name, value);
                    } else {
                        value = Double.valueOf(v);
                    }

                    waitPreSample.put(FieldName.create(name), value);
                }

                return model.predictProba(waitPreSample);

            }
        }

        return -999d;
    }


    /**
     * @Author shen
     * @Description 对缺失值处理成 -999
     * @Date 15:27 2022/11/16
     * @Param [path]
     * @return java.lang.Double
     **/
    private Double exeModelHandMissing(String path) {

        ClassificationModel model = PmmlPool.getInstance().getModel(path);

        List<String> featureNames = model.getFeatureNames();
        Map<FieldName, Number> waitPreSample = new HashMap<>();

        Integer featureLen = featureNames.size();
        Integer missCount = 0;
        for (String name : featureNames) {

            // 获取特征值：
            Double value = -999.0;

            String v = super.get(name);
            if (StringUtil.isEmptyOrNvl(v)) {
                boolean oneHot = FeatureDefinition.isOneHot(name);
                if (oneHot) {
                    value = Double.valueOf(Constant.IS_NO_HIT);
                } else {
                    value = Double.valueOf(Constant.MISSING_VALUE);
                }
                // 设置完成放到map中
                super.put(name, value);
            } else {
                value = Double.valueOf(v);
            }

            if (value.equals(-999.0)) {
                missCount ++;
            }

            waitPreSample.put(FieldName.create(name), value);
        }


        if (missCount >= featureLen) {
            return -999d;
        }

        return model.predictProba(waitPreSample);
    }




    /**
     * @Author shen
     * @Description 执行模型
     * @Date 3:54 下午 2021/3/19
     * @Param []
     * @return java.lang.Double
     **/
    private Double exeModel(String path) {

        ClassificationModel model = PmmlPool.getInstance().getModel(path);

        List<String> featureNames = model.getFeatureNames();
        Map<FieldName, Number> waitPreSample = new HashMap<>();

        for (String name : featureNames) {

            // 获取特征值：
            Double value = -999.0;

            String v = super.get(name);
            if (StringUtil.isEmptyOrNvl(v)) {
                boolean oneHot = FeatureDefinition.isOneHot(name);
                if (oneHot) {
                    value = Double.valueOf(Constant.IS_NO_HIT);
                } else {
                    value = Double.valueOf(Constant.MISSING_VALUE);
                }
                // 设置完成放到map中
                super.put(name, value);
            } else {
                value = Double.valueOf(v);
            }

            waitPreSample.put(FieldName.create(name), value);
        }

        return model.predictProba(waitPreSample);
    }

}
